package org.dream.ui.chart;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JComponent;

import org.dream.ui.chart.impl.ChartModelImpl;

/**
 * @author qiuriyuchen E-mail:panpan_001@126.com
 */
public class Chart extends JComponent {

	private static final long serialVersionUID = 1L;
	protected XAxis xAxis;
	protected Map<Integer, YAxis> yAxisMap = new HashMap<Integer, YAxis>();
	protected Map<Integer, List<Plot>> plotMap = new HashMap<Integer, List<Plot>>();
	protected Color background;

	protected Integer mouseX;
	protected ChartModel chartModel;

	public ChartModel getChartModel() {
		return chartModel;
	}

	// 图例
	private Map<String, Color> tuLi = new LinkedHashMap<String, Color>();

	public Color getTuLi(String bkmc) {
		return tuLi.get(bkmc);
	}

	public void addTuLi(String bkmc, Color color) {
		this.tuLi.put(bkmc, color);
	}

	public Chart(XAxis xAxis, YAxis yAxis) {
		this();
		setAxis(xAxis, yAxis);
	}

	public void setAxis(XAxis xAxis, YAxis yAxis) {

		this.xAxis = xAxis;
		this.xAxis.getXAxisModel().setChartModel(this.chartModel);

		addYAxis(1, yAxis);

	}

	public Chart() {
		// 为了支持鼠标滚动，true时不支持，改为支持键盘，故改为true?此处有疑惑，有时true也支持
		// this.setFocusable(false);
		background = Color.BLACK;
		chartModel = new ChartModelImpl();
	}

	public void addYAxis(int i, YAxis yAxis) {
		yAxis.getYAxisModel().setChartModel(this.chartModel);
		yAxis.getYAxisModel().setIndex(i);
		this.yAxisMap.put(i, yAxis);
		chartModel.setWindowCount(this.yAxisMap.size());
	}

	public void paint(Graphics g) {
		// super.paint(g);
		chartModel.setMargin(0, getYAxis(1).getLabelWidth(g), xAxis.getLabelWidth(g), xAxis.getLabelWidth(g));
		chartModel.setSize(this.getWidth(), this.getHeight());
		// 调用plot的画前方法
		for (int key : plotMap.keySet()) {
			for (int i = 0; i < plotMap.get(key).size(); i++) {
				plotMap.get(key).get(i).beforeDraw();
			}
		}
		// 计算y坐标
		setYaxisMaxAndMinValue();

		g.setColor(background);
		g.fillRect(0, 0, this.getWidth(), this.getHeight());
		xAxis.draw(g);
		for (int key : yAxisMap.keySet()) {
			yAxisMap.get(key).draw(g);
		}
		for (int key : plotMap.keySet()) {
			for (int i = 0; i < plotMap.get(key).size(); i++)
				(plotMap.get(key).get(i)).draw(g);
		}

		// 图例
		int i = 0;
		for (String key : tuLi.keySet()) {
			g.setColor(tuLi.get(key));
			g.drawString(key, chartModel.getPixelXRight() - 20, chartModel.getTopMargin() + 20 + (i * 20));
			i++;
		}

	}

	private void setYaxisMaxAndMinValue() {
		for (int key : yAxisMap.keySet()) {
			if (null == plotMap.get(key) || plotMap.get(key).size() == 0) {
				yAxisMap.get(key).getYAxisModel().setMaxValue(10);
				yAxisMap.get(key).getYAxisModel().setMinValue(0);
				continue;
			}
			for (int i = 0; i < plotMap.get(key).size(); i++) {
				double maxY = plotMap.get(key).get(i).getMaxY();
				double minY = plotMap.get(key).get(i).getMinY();
				if (yAxisMap.get(key).getYAxisModel().getMaxValue() < maxY) {
					yAxisMap.get(key).getYAxisModel().setMaxValue(maxY);
				}
				if (yAxisMap.get(key).getYAxisModel().getMinValue() > minY) {
					yAxisMap.get(key).getYAxisModel().setMinValue(minY);
				}
			}

			// 设置Y轴最小值留空
			// double maxY = yAxisMap.get(key).getYAxisModel().getMaxValue();
			// double minY = yAxisMap.get(key).getYAxisModel().getMinValue();
			// yAxisMap.get(key).getYAxisModel().setMaxValue(maxY * 1.10);
			// yAxisMap.get(key).getYAxisModel().setMinValue(minY * 0.90);
		}
		for (int key : yAxisMap.keySet()) {
			yAxisMap.get(key).getYAxisModel().adjustmentMaxAndMinVale();
		}
	}

	public void clearPlot(String id) {
		for (int key : plotMap.keySet()) {
			for (int i = 0; i < plotMap.get(key).size(); i++) {
				Plot plot = plotMap.get(key).get(i);
				if (plot.getId().equals(id)) {
					plotMap.get(key).remove(i);
					return;
				}
			}

		}
	}

	public XAxis getXAxis() {
		return xAxis;
	}

	public YAxis getYAxis(int i) {
		return yAxisMap.get(i);
	}

	public void setXAxis(XAxis xAxis) {
		this.xAxis = xAxis;
	}

	public void addPlot(Plot plot, int key) {
		if (plotMap.get(key) == null) {
			plotMap.put(key, new ArrayList<Plot>());
		}
		plotMap.get(key).add(plot);
	}

	public void zoom(double zoom) {
		// 如果未画好不执行
		if (Chart.this.chartModel.getUseableWidth() == 0) {
			return;
		}
		int xcoordinate;
		if (null != mouseX) {
			xcoordinate = (int) Chart.this.getXAxis().getXAxisModel().translatePxToValue(mouseX);// 鼠标的X坐标值
		} else {
			xcoordinate = this.getXAxis().getXAxisModel().getMaxValue();// 鼠标的X坐标值
		}

		this.getXAxis().getXAxisModel().zoom(xcoordinate, zoom);

		this.repaint();

	}

	/**
	 * 右为正数，左为负数，数值为步值
	 * 
	 * @param zoom
	 */
	public void move(double zoom) {
		// 如果未画好不执行
		if (Chart.this.chartModel.getUseableWidth() == 0) {
			return;
		}
		this.getXAxis().getXAxisModel().move(zoom);
		this.repaint();

	}

	@Override
	public void repaint() {
		for (int key : yAxisMap.keySet()) {
			yAxisMap.get(key).getYAxisModel().setMaxValue(-Double.MAX_VALUE);
			yAxisMap.get(key).getYAxisModel().setMinValue(Double.MAX_VALUE);

		}
		super.repaint();

		mouseX = null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.dream.ui.chart.Chart#getXCoordinatePixel(double)
	 */
	public int getXCoordinatePixel(double value) {
		return this.getXAxis().getXAxisModel().translateValueToPx(value);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.dream.ui.chart.Chart#getYCoordinatePixel(double, int)
	 */
	public int getYCoordinatePixel(double value, int index) {
		return this.getYAxis(index).getYAxisModel().translateValueToPx(value);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.dream.ui.chart.Chart#getBackground()
	 */
	public Color getBackground() {
		return background;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.dream.ui.chart.Chart#setBackground(java.awt.Color)
	 */
	public void setBackground(Color background) {
		this.background = background;
	}

}
